#include "common/common.h"
#include "string/stringmanipulations.h"
#include "information/piloerrorinformations.h"

#include <wchar.h>
#include <stdio.h>

using namespace PILO::Core::String;

#if defined(WIN32) || defined(WINDOWS)

#else

char * _compat_strerror(char* messageBuffer, int_r bufferSize, ErrorCode number)
{
#   if defined(HAVE_PTHREAD_H)
    char * ret;
    //*messageBuffer = 0;
    ret = strerror_r(number, messageBuffer, bufferSize);	
    if (messageBuffer != ret) {
        strncpy(messageBuffer, ret, bufferSize);
    }
#   else
    strncpy(messageBuffer, strerror(number), bufferSize);
#   endif


    return messageBuffer;
}
#endif

ErrorCode PILOGetLastSystemErrorNumber()
{
#   if defined(WINDOWS)
    return GetLastError();
#   else
    return errno;
#   endif
}

const char* PILOGetLastSystemErrorMessage(char* messageBuffer,int_r bufferSize, ErrorCode number)
{
    char* pRet = messageBuffer;
#   if defined(WINDOWS)
    BOOL fOk = FormatMessage(
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        number,
        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
        (LPTSTR) messageBuffer,
        (DWORD) bufferSize, NULL );
    if (!fOk) {
        HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
        if (hDll != NULL) {
            FormatMessage(
                FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM ,
                hDll,
                number,
                MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
                (LPTSTR) messageBuffer,
                (DWORD) bufferSize, NULL );
            FreeLibrary(hDll);
        }
    }

#   else
    _compat_strerror(messageBuffer, bufferSize, number);
#endif

    PILO::Core::String::StringTrimRight(messageBuffer);
    return pRet;

}

const wchar_t * PILOGetLastSystemErrorMessage(wchar_t * messageBuffer,int_r bufferSize, ErrorCode number)
{
    wchar_t * pRet = messageBuffer;

#   if defined(WINDOWS)
    BOOL fOk = FormatMessage(
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        number,
        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
        (LPTSTR) messageBuffer,
        (DWORD) bufferSize, NULL );
    if (!fOk) {
        HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
        if (hDll != NULL) {
            FormatMessage(
                FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM ,
                hDll,
                number,
                MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
                (LPTSTR) messageBuffer,
               (DWORD) bufferSize, NULL );
            FreeLibrary(hDll);
        }
    }

#   else
    char tmpBuffer[MC_SYSTEM_ERROR_MESSAGE_MAX_CHAR];
    _compat_strerror(tmpBuffer, sizeof(tmpBuffer), number);
    PILO::Core::String::_compat_mbstowcs(messageBuffer,tmpBuffer, sizeof(tmpBuffer) );
#   endif

    PILO::Core::String::StringTrimRight(messageBuffer);
    return pRet;
}

TriState PILOGetLastSystemError(char * messageBuffer, int_r bufferSize)
{
    if (MC_NULLPTR_OF_(char*) == messageBuffer) {
        return EnumTriStateNA;
    }

    ErrorCode err = PILOGetLastSystemErrorNumber();
    if (MC_SUCCESS == err) {
        return EnumTriStateNo;
    }

    PILOGetLastSystemErrorMessage(messageBuffer, bufferSize, err);
    return EnumTriStateYes;
}

TriState PILOGetLastSystemError(wchar_t * messageBuffer, int_r bufferSize)
{
    if (MC_NULLPTR_OF_(wchar_t*) == messageBuffer) {
        return EnumTriStateNA;
    }

    ErrorCode err = PILOGetLastSystemErrorNumber();
    if (MC_SUCCESS == err) {
        return EnumTriStateNo;
    }

    PILOGetLastSystemErrorMessage(messageBuffer, bufferSize, err);
    return EnumTriStateYes;
}

